package com.maiji.cloud.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.mapper.Wrapper;
import com.baomidou.mybatisplus.plugins.Page;
import com.maiji.cloud.entities.login.*;
import com.maiji.cloud.mapper.*;
import com.maiji.cloud.microservice.GoodsService;
import com.maiji.cloud.request.BaseDataReqDto;
import com.maiji.cloud.request.ReqMetaData;
import com.maiji.cloud.request.login.FoodReqData;
import com.maiji.cloud.request.login.FoodFindAllReqData;
import com.maiji.cloud.response.*;
import com.maiji.cloud.response.login.FoodMaterialDetialResDto;
import com.maiji.cloud.response.login.FoodMaterialResData;
import com.maiji.cloud.response.login.UploadImageResData;
import com.maiji.cloud.response.shopingmall.GoodsResData;
import com.maiji.cloud.service.*;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.maiji.cloud.utils.*;
import org.apache.commons.compress.utils.Lists;
import org.apache.poi.ss.usermodel.*;
import org.eclipse.jetty.util.StringUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.Resource;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.net.URI;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Transactional
public class FoodMaterialServiceImpl extends ServiceImpl<FoodMaterialMapper, FoodMaterialEntity> implements FoodMaterialService {

    private static final Logger logger = LoggerFactory.getLogger(FoodMaterialServiceImpl.class);
    @Autowired
    private NutrientContentService nutrientContentService;
    @Autowired
    private NutrientContentMapper nutrientContentMapper;
    @Autowired
    private UploadRecordService uploadRecordService;
    @Autowired
    private FoodMiddleGoodsService foodMiddleGoodsService;
    @Autowired
    private LabelMiddleFoodMaterialService labelMiddleFoodMaterialService;
    @Autowired
    private LabelMiddleFoodMaterialMapper labelMiddleFoodMaterialMapper;
    @Autowired
    private FoodMaterialMapper foodMaterialMapper;
    @Autowired
    private LabelService labelService;
    @Autowired
    private LabelMapper labelMapper;
    @Autowired
    private GoodsService goodsService;
    @Autowired
    private FoodMaterialTypeLableService foodTypeService;
    @Autowired
	private FoodMaterialCollectionMapper foodMaterialCollectionMapper;

    @Override
    public FoodMaterialDetialResDto getFoodMaterialDetailById(String foodId) {
        logger.info("DietServiceImpl.getFoodMaterialDetailById,param is {}",
                JSON.toJSONString(foodId));

        FoodMaterialEntity foodMaterialEntity = foodMaterialMapper.selectOneById(foodId);
        
       

        List<NutrientContentEntity> nutrientContentEntityList = nutrientContentMapper
                .selectListByFoodMaterialId(foodMaterialEntity.getUuId());

        FoodMaterialDetialResDto foodMaterialDetialResDto = new FoodMaterialDetialResDto(Status.SUCCESS);

        FoodMaterialResData foodMaterialResData = new FoodMaterialResData();

        BeanUtils.copyProperties(foodMaterialEntity, foodMaterialResData);
        Integer count = foodMaterialCollectionMapper.getSumByfoodMaterialId(foodId);
        
        if(count == null || count == 0) {
        	foodMaterialResData.setIsCollection(0);
        }else {
        	foodMaterialResData.setIsCollection(1);
        }

        Wrapper<UploadRecord> wrapper = new EntityWrapper<UploadRecord>()
                .eq("belong_id", foodMaterialEntity.getUuId())
                .eq("is_main", 1);
        UploadRecord uploadRecord = uploadRecordService.selectOne(wrapper);
        if (uploadRecord != null) {
            UploadImageResData imgData = new UploadImageResData();
            BeanUtils.copyProperties(uploadRecord, imgData);
            if(uploadRecord.getWidth() == null || uploadRecord.getHeight() == null) {
            	Map<String,Integer> map = UploadUtil.getWidthOrHeightByImgURL(imgData.getUrl());
            	imgData.setWidth(map.get("width"));
            	imgData.setHeight(map.get("height"));
            }
            imgData.setSmallUrl(imgData.getUrl()+""+ CommonStringValueEnum.IMAGE_URL_SMALL.getValue());
            foodMaterialResData.setImgData(imgData);
        }

        foodMaterialResData.setNutrientContentEntityList(nutrientContentEntityList);

        List<LabelMiddleFoodMaterial> laybelMiddleFoodMaterialList = labelMiddleFoodMaterialMapper
                .selectListByFoodMaterialId(foodMaterialEntity.getUuId());
        // 阶段标签id集合
        List<String> laybelIds = new ArrayList<>();
        for (LabelMiddleFoodMaterial laybelMiddleFoodMaterial : laybelMiddleFoodMaterialList) {
            laybelIds.add(laybelMiddleFoodMaterial.getLabelId());
        }
        List<Label> list = Lists.newArrayList();
        if (laybelIds.size() != 0) list = labelMapper.selectBatchIds(laybelIds);
        foodMaterialResData.setLabelList(list);

        foodMaterialDetialResDto.setData(foodMaterialResData);
        return foodMaterialDetialResDto;
    }

    @Override
    public BaseMetaResDto<List<FoodMaterialResData>> findAllFoods(FoodFindAllReqData data, ReqMetaData reqMetaData) {
        Integer pageNo = reqMetaData.getPage();
        Integer pageSize = reqMetaData.getSize();
        Page<FoodMaterialResData> page = new Page<>(pageNo, pageSize);
        List<FoodMaterialResData> allFoods = foodMaterialMapper.findAllFoods(data, page);
        if (allFoods == null) return new BaseMetaResDto<>(Status.ERROR);
        List<String> foodIds = allFoods.stream().map(FoodMaterialResData::getUuId).collect(Collectors.toList());
        Map<String, List<NutrientContentEntity>> ncsMap = nutrientContentService.selectList(
                new EntityWrapper<NutrientContentEntity>().in("food_material_id", foodIds))
                .stream().collect(Collectors.groupingBy(NutrientContentEntity::getFoodMaterialId));
        allFoods.stream().forEach(food -> food.setNutrientContentEntityList(ncsMap.get(food.getUuId())));
        ResMetaData resMetaData = new ResMetaData(pageNo, pageSize, page.getTotal());
        return new BaseMetaResDto<List<FoodMaterialResData>>(Status.SUCCESS).setData(allFoods).setResMetaData(resMetaData);
    }

    @Override
    public BaseResDto delFoodsByIds(List<String> foodIds) {
        if (! deleteBatchIds(foodIds)) return new BaseResDto(Status.ERROR);
        return new BaseResDto(Status.SUCCESS);
    }

    @Override
    public BaseResDto addFood(FoodReqData data) throws Exception {
        String foodId = UUID_MD5.getUUID();
        FoodMaterialEntity food = new FoodMaterialEntity().setUuId(foodId)
                .setName(data.getName())
                .setAlias(data.getAlias())
                .setDescription(data.getDescription())
                .setRemark(data.getRemark())
                .setInTime(new Date())
                .setCascaderStr(data.getCascaderStr())
                .setTypeLabelId(data.getTypeLabelId());
        UploadRecord mainImg = new UploadRecord().setUuId(data.getMainImageId()).setBelongId(foodId).setIsMain(1);
        if (! uploadRecordService.updateById(mainImg)) return new BaseResDto(Status.ERROR.setMessage("保存食材主图失败"));
        List<UploadRecord> uploadRecords = Lists.newArrayList();
        String detailsText = DetailTextUtil.dealDetailText(MaijiOSS.OSSFOODBUKET, foodId, data.getDetailText(), uploadRecords);
        if (uploadRecords.size() > 0 && ! uploadRecordService.insertBatch(uploadRecords)) return new BaseResDto(Status.ERROR.setMessage("保存食材详情图片失败！"));
        List<NutrientContentEntity> ncs = data.getNcs().stream().map(RecipeIngredient ->
                RecipeIngredient.setUuId(UUID_MD5.getUUID()).setFoodMaterialId(foodId)).collect(Collectors.toList());
        if (ncs.size() > 0 && ! nutrientContentService.insertBatch(ncs)) return new BaseResDto(Status.ERROR.setMessage("保存食材营养元素失败！"));
        if (data.getGoods().size() > 0) {
            List<FoodMiddleGoods> goods = data.getGoods().stream().map(fmg -> fmg.setUuId(UUID_MD5.getUUID()).setFoodId(foodId)).collect(Collectors.toList());
            if (! foodMiddleGoodsService.insertBatch(goods)) return new BaseResDto(Status.ERROR.setMessage("保存食材关联商品失败！"));
        }
        if (! insert(food.setDetailText(detailsText))) return new BaseResDto(Status.ERROR.setMessage("保存食材失败！"));
        List<LabelMiddleFoodMaterial> labelMiddleFoodMaterials = data.getLabels().stream().map(lmf ->
                lmf.setUuId(UUID_MD5.getUUID()).setFoodMaterialId(foodId)).collect(Collectors.toList());
        if (labelMiddleFoodMaterials.size() > 0 && ! labelMiddleFoodMaterialService.insertBatch(labelMiddleFoodMaterials))
            return new BaseResDto(Status.ERROR.setMessage("保存食材标签失败！"));
        return new BaseResDto(Status.SUCCESS);
    }

    @Override
    public BaseResDto editFood(FoodReqData data) throws Exception {
        String foodId = data.getUuId();
        if (StringUtil.isBlank(foodId)) return new BaseResDto(Status.PARAMETERERROR.setMessage("参数错误：uuId不可为空！"));
        String mainImageId = data.getMainImageId();
        EntityWrapper<UploadRecord> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("belong_id", foodId);
        entityWrapper.eq("is_main", 1);
        UploadRecord mainImg = uploadRecordService.selectOne(entityWrapper);
        if (mainImg == null || ! mainImg.getUuId().equals(mainImageId)) {
            List<UploadRecord> uploadRecords = Lists.newArrayList();
            if (mainImg != null) uploadRecords.add(mainImg.setBelongId(""));
            uploadRecords.add(new UploadRecord().setUuId(mainImageId).setBelongId(foodId).setIsMain(1));
            if (! uploadRecordService.updateBatchById(uploadRecords)) return new BaseResDto(Status.ERROR.setMessage("编辑食材主图失败！"));
        }
        List<NutrientContentEntity> ncs = data.getNcs();
        if (ncs.stream().anyMatch(food -> StringUtil.isBlank(food.getUuId()))) {
            ncs = ncs.stream().map(food -> food.setUuId(UUID_MD5.getUUID()).setFoodMaterialId(foodId)).collect(Collectors.toList());
            if (nutrientContentService.delete(new EntityWrapper<NutrientContentEntity>().eq("food_material_id", foodId)) &&
                ! nutrientContentService.insertBatch(ncs)) return new BaseResDto(Status.ERROR.setMessage("编辑食材营养元素失败！"));
        }
        List<UploadRecord> uploadRecords = Lists.newArrayList();
        String detailsText = DetailTextUtil.dealDetailText(MaijiOSS.OSSFOODBUKET, foodId, data.getDetailText(), uploadRecords);
        if (uploadRecords.size() > 0 && ! uploadRecordService.insertBatch(uploadRecords)) return new BaseResDto(Status.ERROR.setMessage("编辑食材详情失败！"));
        if (! labelMiddleFoodMaterialService.delete(new EntityWrapper<LabelMiddleFoodMaterial>().eq("food_material_id", foodId))) return new BaseResDto(Status.ERROR.setMessage("编辑食材标签失败！"));
        List<LabelMiddleFoodMaterial> labels = data.getLabels();
        if (labels.size() > 0) {
            labels = labels.stream().map(label -> label.setUuId(UUID_MD5.getUUID()).setFoodMaterialId(foodId)).collect(Collectors.toList());
            if (! labelMiddleFoodMaterialService.insertBatch(labels)) return new BaseResDto(Status.ERROR.setMessage("编辑食材标签失败！"));
        }
        List<FoodMiddleGoods> fmgs = data.getGoods().stream().map(label -> label.setUuId(UUID_MD5.getUUID()).setFoodId(foodId)).collect(Collectors.toList());
        if (! foodMiddleGoodsService.delete(new EntityWrapper<FoodMiddleGoods>().eq("food_id", foodId)))
            return new BaseResDto(Status.ERROR.setMessage("编辑食材关联商品失败！"));
        if (fmgs.size() > 0 && !foodMiddleGoodsService.insertBatch(fmgs))
            return new BaseResDto(Status.ERROR.setMessage("编辑食材关联商品失败！"));
        FoodMaterialEntity foodMaterialEntity = new FoodMaterialEntity();
        BeanUtils.copyProperties(data, foodMaterialEntity);
        foodMaterialEntity.setDetailText(detailsText);
        if (! updateById(foodMaterialEntity)) return new BaseResDto(Status.ERROR.setMessage("编辑食材数据失败！"));
        return new BaseResDto(Status.SUCCESS);
    }

    @Override
    public BaseDataResDto<List<Label>> findAllLabelsByFoodId(String foodId) {
        EntityWrapper<LabelMiddleFoodMaterial> entityWrapper = new EntityWrapper<>();
        entityWrapper.eq("food_material_id", foodId);
        List<String> labelIds = labelMiddleFoodMaterialService.selectList(entityWrapper).stream()
                .map(LabelMiddleFoodMaterial::getLabelId).collect(Collectors.toList());
        if (labelIds.size() == 0) return new BaseDataResDto<List<Label>>(Status.SUCCESS).setData(Lists.newArrayList());
        List<Label> labels = labelService.selectBatchIds(labelIds);
        return new BaseDataResDto<List<Label>>(Status.SUCCESS).setData(labels);
    }

    @Override
    public BaseDataResDto<String> uploadFoods(MultipartFile uploadFile) throws Exception {
        List<FoodMaterialEntity> foods = Lists.newArrayList();
        ArrayList<NutrientContentEntity> ncs = Lists.newArrayList();
        List<LabelMiddleFoodMaterial> labelMiddleFoods = Lists.newArrayList();
        Label label1 = labelService.selectOne(new EntityWrapper<Label>().eq("name", "第一阶段").eq("source", "食材"));
        Label label2 = labelService.selectOne(new EntityWrapper<Label>().eq("name", "第二阶段").eq("source", "食材"));
        Workbook workbook = WorkbookFactory.create(uploadFile.getInputStream());
        StringBuffer errorTxt = new StringBuffer();
        for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
            Sheet sheet = workbook.getSheetAt(i);
            for (int j = 0; j <= sheet.getPhysicalNumberOfRows(); j++) {
                Row row = sheet.getRow(j);
                if (j == 0) {  //标题行
                    errorTxt.append("错误行号\t错误信息提示\r\n");
                    continue;
                }
                if (row == null) continue;  //没数据
                String foodId = UUID_MD5.getUUID();
                FoodMaterialEntity food = new FoodMaterialEntity().setUuId(foodId);
                Boolean flag = true;
                rowFor: for (int k = 0; k < 12; k++) {
                    String cellValue =  row.getCell(k)!=null? row.getCell(k).getStringCellValue(): null;
                    switch (k) {
                        case 0:
                            if (StringUtil.isBlank(cellValue)) {
                                errorTxt.append(j+1 + "\t\t\t二级分类名称不可为空\r\n");
                                flag = false;
                                break rowFor;
                            }
                            EntityWrapper<FoodMaterialTypeLable> entityWrapper = new EntityWrapper();
                            entityWrapper.eq("name", cellValue);
                            entityWrapper.ne("parent_id", "0");
                            FoodMaterialTypeLable foodType = foodTypeService.selectOne(entityWrapper);
                            if (foodType == null) {
                                errorTxt.append(j+1 + "\t\t\t二级分类名称错误\r\n");
                                flag = false;
                                break rowFor;
                            }
                            food.setTypeLabelId(foodType.getUuId()).setCascaderStr(foodType.getParentId() + "," + foodType.getUuId());
                            break;
                        case 1:
                            if (StringUtil.isBlank(cellValue)) {
                                errorTxt.append(j+1 + "\t\t\t食材名称不可为空\r\n");
                                flag = false;
                                break rowFor;
                            }
                            food.setName(cellValue);
                            break;
                        case 2:
                            if (StringUtil.isBlank(cellValue)) continue;
                            food.setAlias(cellValue);
                            break;
                        case 3:
                            if (StringUtil.isBlank(cellValue)) continue;
                            String[] goodsIds = cellValue.split("、");
                            List<FoodMiddleGoods> fmgs = Arrays.asList(goodsIds).stream().map(goodsId -> new FoodMiddleGoods()
                                    .setUuId(UUID_MD5.getUUID())
                                    .setFoodId(foodId)
                                    .setGoodsId(goodsId)).collect(Collectors.toList());
                            foodMiddleGoodsService.insertBatch(fmgs);
                            break;
                        case 4:
                            if (StringUtil.isBlank(cellValue)) {
                                errorTxt.append(j+1 + "\t\t\t食材热量不可为空\r\n");
                                flag = false;
                                break rowFor;
                            }
                            ncs.add(new NutrientContentEntity()
                                    .setUuId(UUID_MD5.getUUID())
                                    .setFoodMaterialId(foodId)
                                    .setElement("热量")
                                    .setValue(cellValue));
                            break;
                        case 5:
                            if (StringUtil.isBlank(cellValue)) continue;
                            ncs.add(new NutrientContentEntity()
                                    .setUuId(UUID_MD5.getUUID())
                                    .setFoodMaterialId(foodId)
                                    .setElement("蛋白质")
                                    .setValue(cellValue));
                            break;
                        case 6:
                            if (StringUtil.isBlank(cellValue)) continue;
                            ncs.add(new NutrientContentEntity()
                                    .setUuId(UUID_MD5.getUUID())
                                    .setFoodMaterialId(foodId)
                                    .setElement("脂肪")
                                    .setValue(cellValue));
                            break;
                        case 7:
                            if (StringUtil.isBlank(cellValue)) continue;
                            ncs.add(new NutrientContentEntity()
                                    .setUuId(UUID_MD5.getUUID())
                                    .setFoodMaterialId(foodId)
                                    .setElement("碳水化合物")
                                    .setValue(cellValue));
                            break;
                        case 8:
                            if (StringUtil.isBlank(cellValue)) continue;
                            ncs.add(new NutrientContentEntity()
                                    .setUuId(UUID_MD5.getUUID())
                                    .setFoodMaterialId(foodId)
                                    .setElement("膳食纤维")
                                    .setValue(cellValue));
                            break;
                        case 9:
                            if (StringUtil.isBlank(cellValue)) continue;
                            food.setDescription(cellValue);
                            break;
                        case 10:
//                            if (StringUtil.isBlank(cellValue)) {
//                                errorTxt.append(j+1 + "\t\t\t食材名主图不可为空\r\n");
//                                flag = false;
//                                break rowFor;
//                            }
                            if (StringUtil.isNotBlank(cellValue)) {
                                String bucketName = "maiji-food-images";
                                String objName = UUID_MD5.getUUID() + ".jpg";
                                ResponseEntity<Resource> entity = new RestTemplate().postForEntity(new URI(cellValue), null, Resource.class);
                                InputStream inputStream = entity.getBody().getInputStream();
                                MaijiOSS.aliyunOSSUpload2(bucketName, objName, inputStream);
                                uploadRecordService.insert(new UploadRecord()
                                        .setUuId(UUID_MD5.getUUID())
                                        .setBelongId(foodId)
                                        .setUploadUserId("admin-1234567890")
                                        .setFileName(objName)
                                        .setUrl("https://" + bucketName + ".oss-cn-beijing.aliyuncs.com/" + objName)
                                        .setUploadTime(new Date())
                                        .setIsMain(1).setNo(0));
                            }
                            break;
                        case 11:
                            if (cellValue.equals("可食用")) {
                                labelMiddleFoods.add(new LabelMiddleFoodMaterial()
                                    .setUuId(UUID_MD5.getUUID())
                                .setFoodMaterialId(foodId)
                                .setLabelId(label1.getUuId()));
                            }
                            break;
                        case 12:
                            if (cellValue.equals("可食用")) {
                                labelMiddleFoods.add(new LabelMiddleFoodMaterial()
                                    .setUuId(UUID_MD5.getUUID())
                                .setFoodMaterialId(foodId)
                                .setLabelId(label2.getUuId()));
                            }
                            break;
                    }
                }
                if (flag) foods.add(food.setInTime(new Date()));
            }
        }
        if (foods.size() != 0) if (! insertBatch(foods)) return new BaseDataResDto<>(Status.ERROR);;
        if (ncs.size() != 0) if (! nutrientContentService.insertBatch(ncs)) return new BaseDataResDto<>(Status.ERROR);;
        if (labelMiddleFoods.size() != 0) if (! labelMiddleFoodMaterialService.insertBatch(labelMiddleFoods)) return new BaseDataResDto<>(Status.ERROR);
        if (errorTxt.toString().length() > 13) return new BaseDataResDto<String>(Status.SUCCESS).setData(errorTxt.toString());
        return new BaseDataResDto(Status.SUCCESS);
    }

    @Override
    public BaseMetaResDto<List<GoodsResData>> findAllGoodsByFoodIds(List<String> foodIds, ReqMetaData metaData) {
        Wrapper<FoodMiddleGoods> wrapper = new EntityWrapper<FoodMiddleGoods>().in("food_id", foodIds);
        List<String> goodsIds = foodMiddleGoodsService.selectList(wrapper).parallelStream().map(FoodMiddleGoods::getGoodsId).collect(Collectors.toList());
        if (goodsIds.size() == 0) return new BaseMetaResDto(Status.SUCCESS);
        BaseDataReqDto<List<String>> baseDataReqDto = new BaseDataReqDto<>();
        baseDataReqDto.setData(goodsIds);
        baseDataReqDto.setMetaData(metaData);
        return goodsService.findAllGoodsByIds(baseDataReqDto);
    }

}
